Compose Multiplatform で画面遷移をおこなう
この記事では、Compose Multiplatform(以下、CMP)を使用して、画面遷移する方法を紹介する。例として起動画面からホーム画面へ画面遷移をおこなう。
Compose Multiplatformとは
CMPは、複数のプラットフォームに対応したUIを構築する宣言的フレームワークだ。KotlinとComposeを使用してAndroidとiOSで同じUIを共有するアプリを開発できる。プラットフォーム間でのコードの再利用性が高くなり、開発効率が大幅に向上することを期待している。
CMPプロジェクトを作成する方法、AndroidエミュレータとiOSシミュレータとで実行する方法を以下の記事で紹介している。
開発環境
- MacBook Pro (16インチ, 2021)
- macOS Sonoma 14.5
- Xcode 15.4
- Android Studio Jellyfish | 2023.3.1 Patch 1
- Compose Plugin 1.6.10
Compose Multiplatform で画面遷移をおこなう
CMPを使用することで、同じコードベースでAndroidとiOSの両方に対応したアプリを開発できる。ここでは、ナビゲーションライブラリを使用して、起動画面からホーム画面への遷移を実装する手順を紹介する。
1. Navigation依存関係の追加
まず、Gradle バージョン カタログ(gradle/libs.versions.toml
ファイル)を開き、Navigation Componentの利用するバージョンとライブラリの定義を追加する。
[versions] androidx-navigation = "2.8.0-alpha02" ... [libraries] androidx-navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
次に build.gradle.kts
ファイルの commonMain.dependencies
に依存関係を追加する。
kotlin { sourceSets { commonMain.dependencies { //... implementation(libs.androidx.navigation.compose) // <--- Add } } }
2. NavHostの設定
次に、NavHost
を使ってナビゲーションを設定する。AppNavHost
を作成し、ナビゲーションの開始地点を指定している。
import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @Composable fun AppNavHost( navController: NavHostController = rememberNavController(), ) { NavHost( navController = navController, startDestination = "launch", ) { composable("launch") { LaunchScreen(navController) } composable("home") { HomeScreen() } } }
元々定義されている App
を削除し、新しく AppNavHost
を表示するように変更する。
import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import org.jetbrains.compose.ui.tooling.preview.Preview @Composable @Preview fun App() { MaterialTheme { AppNavHost() } }
3. 起動画面とホーム画面を追加する
起動画面では CircularProgressIndicator
を使って、ぐるぐる回るインジケータを表示させる。ここでは紹介しないが、この画面では、強制アップデートの可否を確認する処理や、マスタデータのダウンロードなどの処理を想定している。
@Composable fun LaunchScreen() { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { CircularProgressIndicator() } }
ホーム画面では、ホーム画面であることを示す Text
だけを表示する。
@Composable fun HomeScreen() { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = "Welcome to Home Screen") } }
4. LaunchScreenからHomeScreenへの遷移
起動画面が表示されたときに2秒間遅延させ、その後にホーム画面に遷移させる。画面遷移時の処理をおこなうのにLaunchedEffect
を使っている。
@Composable fun LaunchScreen( navController: NavHostController ) { LaunchedEffect(Unit) { delay(2000) // 2秒待つ navController.navigate("home") } Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { CircularProgressIndicator() } }
アプリを実行する
最後に、起動画面からホーム画面へ画面遷移できるか確認する。
Androidエミュレータでアプリを実行する
Android エミュレータ上で起動画面からホーム画面への遷移を確認できた。
iOSシミュレータでアプリを実行する
iOSシミュレータ上で起動画面からホーム画面への遷移を確認できた。
以上で、iOS/Androidともに、同一のコードから画面遷移を実現することが確認できた。
(2024/06/17追記) CMPでプラットフォーム固有のコンポーネントを表示する
ひとつのコードベースからiOSとAndroidで同じUIを実装できるのがCompose Multiplatformの利点ではあるが、UIについてはそれぞれのプラットフォームでの世界観が存在している。たとえば今回、ぐるぐる回るインジケータをCircularProgressIndicator
で実装したが、iOSでは対応するUIコンポーネントは UIActivityIndicatorView
になる。
expect
とactual
宣言を利用して、各プラットフォームで表示するUIコンポーネントを使い分けることができる。本質的なものではないため、こだわるのであればあくまでもアプリが完成してからが良いと思うが、各プラットフォームでの世界観を守るために細部に手を入れると良いだろう。